<?php

	class AKB_HELPER
	{
		var $catsById = array();
		var $questionCountByCatId =  array();
		var $catsCached = false;

		var $categoryRestrictOverride = false; //If true, then we dont take into account the categoryRestrictOption config variable.

		function AKB_HELPER()
		{
			$this->tree = new Tree();
		}

		/**
		* GetCategoryOptions
		* Get an html options box with categories in it. Categories which are pre
		* selected can be specified as can the format of the html
		*
		* @param array $SelectedCats The cats to pre select in the list
		* @param string $Container The html to use for the option
		* @param string $sel The html to use to signify a cat is selected
		* @param string $Divider The text to prefix sub cats with
		*
		* @return string The html for the options
		*/
		function GetCategoryOptions_DEPRECATED($SelectedCats, $Container=null, $sel='selected="selected"', $Divider='- ')
		{
			if ($Container === null) {
				$Container = $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryOptionsDefaultContainer');
			}

			// Get a list of categories as <option> tags
			$cats = '';

			if (!is_array($SelectedCats)) {
				$SelectedCats = array();
			}

			$categories = $this->getCats($Divider);
			
			foreach ($categories as $cid => $cname) {
				$s = (in_array($cid,$SelectedCats)) ? $sel : '';
				$cats .= sprintf($Container, $s, $cid, $cname);
			}
			return $cats;
		}
		
		/**
		* GetCategoryOptions
		* Get an html options box with categories in it. Categories which are pre
		* selected can be specified as can the format of the html
		*
		* @param array $SelectedCats The cats to pre select in the list
		* @param string $Container The html to use for the option
		* @param string $sel The html to use to signify a cat is selected
		* @param string $Divider The text to prefix sub cats with
		* @param bool $IncludeEmpty Add an option at the top for "
		* please select a category"
		* @param array $hide If not empty then hide catids in this array
		*
		* @return string The html for the options
		*/
		function GetCategoryOptions($SelectedCats, $Container = "<option %s value='%d'>%s</option>", $Sel = "selected=\"selected\"", $Divider = "- ", $IncludeEmpty = true)
		{
			// Get a list of categories as <option> tags
			$cats = '';

			// Make sure $SelectedCats is an array
			if (!is_array($SelectedCats)) {
				$SelectedCats = array();
			}

			if (empty($SelectedCats) || in_array("0", $SelectedCats)) {
				$sel = "selected = \"selected\"";
			} else {
				$sel = "";
			}

			// Get a formatted list of all the categories in the system
			$categories = $this->getCats($Divider);

			// Work out which cats we want to keep in the list
			$this->getCatsInfo();

			$permitted = array();
			if (isset($GLOBALS['categoryRestrictOption']) && $GLOBALS['categoryRestrictOption'] == "1") {
				$permitted = $this->GetPermittedCats();
			}
			
			if (!empty($permitted)) {
				$cats_to_keep = $permitted;
				foreach ($permitted as $catid) {
					if (is_array($cats_to_keep) && is_array($this->tree->GetBranchTo((int) $catid))) {
						$cats_to_keep = array_merge($cats_to_keep, $this->tree->GetBranchTo((int) $catid));
					}
				}
			} else {
				// There are no restrictions on which cats we can see
				$cats_to_keep = array_keys($categories);
			}

			foreach ($categories as $cid => $cname) {
				$row = $this->catsById[$cid];
				
				if (!in_array($cid, $cats_to_keep) && $row['security'] == 'private') {
					continue;
				}

				if (!empty($permitted) && !in_array($cid, $permitted) &&  $row['security'] == 'private' && $_SESSION['user']->userid != 1) {
					// if there are category restrictions in place
					// and this category isn't one that we are allowed access to
					// and we arnt the super user
					$cats .= sprintf($Container, 'disabled', $cid, $cname);
				} else if ((empty($permitted) || in_array($cid, $permitted) || $_SESSION['user']->userid == 1) || (!empty($permitted) && !in_array($cid, $permitted) &&  $row['security'] == 'public')) {
					if (in_array($cid, $SelectedCats)) {
						$s = $Sel;
					} else {
						$s = '';
					}
					$cats .= sprintf($Container, $s, $cid, strip_tags($cname));
				}
			}
			return $cats;
		}

		/**
		* getCatsInfo
		* Get all the information for the categories and save them in the arrays
		* $this->catsById to signify what each of them
		* is indexed by. All functions accessing categories should check to see
		* if one of these arrays already has values and if its empty, call this
		* function to populate it. This allows the arrays to serve as a cache
		* ensuring that the database isn't hit excessively for info on cats
		*
		* @return void
		*/
		function getCatsInfo()
		{
			if ($this->catsCached) {
				return;
			}
			
			//If we're in here then we're gonna reload the cats. So we need to refresh the vars used.
			$this->tree = new Tree();
			$this->catsById = null;
			
			//If we're not logged in and the categoryRestrictOption is set to hide (1), only select the public.
			$whereSecurity = "";
			
			$user = AKB_AUTH::GetLoggedInUser();
			
			//(If we're not logged in) OR (we dont have any groups associated with this user AND its not an admin user) AND (we DONT want to see links [CRO:1]) OR (we're overriding the category restriction)
			//...then we only want to grab the public categories.
			if (((!$user) || ((isset($user->groups)) && (!$user->groups) && ($user->userid > 1))) && ((isset($GLOBALS['categoryRestrictOption']) && $GLOBALS['categoryRestrictOption'] == "1") || ($this->categoryRestrictOverride))) {
				$whereSecurity = "WHERE security = 'public'";
			}
			
			$query = "SELECT *
				FROM ".$GLOBALS['tablePrefix']."categories
				".$whereSecurity."
				ORDER BY catorder, name ";
			
			$result = $GLOBALS['AKB_DB']->Query($query);
			while ($row = $GLOBALS['AKB_DB']->Fetch($result)) {
				$row = $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders($row);
				$this->catsById[$row['categoryid']] = $row;
				$this->tree->nodesByPid[(int) $row['parentid']][] = (int) $row['categoryid'];
			}
			
			//Reset the category override in case this gets called twice.
			$this->categoryRestrictOverride = false;

			//Set the category caching to true
			$this->catsCached = true;
		}

		/**
		* getQuestCountInfo
		* Get the number of questions in a category and save it to the array
		* $this->questionCountByCatId in case we want to use it again later
		*
		* @return void
		*/
		function getQuestCountInfo()
		{
			$questionCat = array();
			$workflowQry = "";
			if (validUrl()) {
				$workflowQry = 'AND (q.workflowstatus = \''.WF_STATUS_APPROVED.'\' OR q.workflowstatus = \''.WF_STATUS_AUTO_APPROVED.'\' OR q.workflowstatus = \''.WF_STATUS_REPENDING.'\' '.getShowDisapprovedArticleString('OR', 'q.').') ';
			}
			
			$categoryRestrictSQL = "";
			if (isset($GLOBALS['categoryRestrictOption']) && $GLOBALS['categoryRestrictOption'] == "1") {
				// permitted category
				$accessible_cats = $GLOBALS['AKB_CLASS_HELPER']->GetPermittedCats();
				// public category
				$query = sprintf("SELECT categoryid FROM %scategories WHERE security = '%s' ",$GLOBALS['tablePrefix'],'public');
				$result = $GLOBALS['AKB_DB']->Query($query);
				while ($row = $GLOBALS['AKB_DB']->Fetch($result)) {
					$accessible_cats[] = $row['categoryid'];
				}
				$accessible_cats = array_unique($accessible_cats);
				$categoryRestrictSQL = "AND a.categoryid IN (".implode(", ", $accessible_cats).")";
			}
			
			$query = "SELECT DISTINCT a.categoryid, a.questionid, q.workflowstatus
				FROM 
					".$GLOBALS['tablePrefix']."categories c,
					".$GLOBALS['tablePrefix']."categoryassociations a,
					".$GLOBALS['tablePrefix']."catassoc_history ca,
					(".$GLOBALS['tablePrefix']."question_auth qa RIGHT JOIN ".$GLOBALS['tablePrefix']."questions q ON qa.questionid = q.questionid)
				WHERE a.questionid = q.questionid
				AND a.categoryid = c.categoryid
				AND a.categoryid = ca.categoryid
				AND a.questionid = ca.questionid
				AND q.visible = 1
				".$workflowQry."
				AND
					(
						((q.startdate < '".$GLOBALS['currDatetime']."') AND ((q.enableexpiry = 1) AND q.expirydate > '".$GLOBALS['currDatetime']."'))
						OR
						((q.startdate < '".$GLOBALS['currDatetime']."') AND (q.enableexpiry = 0))
					)
				".$categoryRestrictSQL."
				AND (qa.groupid IS NULL ".AKB_AUTH::deriveGroupSQL(false).")
				GROUP BY a.categoryid, a.questionid, q.workflowstatus ";
			$result = $GLOBALS['AKB_DB']->Query($query);
			$this->questionCountByCatId = array();

			$validStatus = getShowDisapprovedArticleArray();
			if ($GLOBALS['AKB_DB']->CountResult($query) > 0) {
				$historyQuestionIds = array();
				while ($row = $GLOBALS['AKB_DB']->Fetch($result)) {
					if (validUrl()) {
						if (!in_array($row['workflowstatus'], $validStatus)) {
							$questionCat[$row['questionid']][] = $row['categoryid'];
						} else {
							$historyQuestionIds[] = trim($row['questionid']);
						}
					} else {
						$questionCat[$row['questionid']][] = $row['categoryid'];
					}
				}
				if (sizeof($historyQuestionIds)) {
					$historyQuestionIdsStr = "'" . implode("','", $historyQuestionIds) . "'";
					$historyQuestionIdsQry = "SELECT  DISTINCT  qh.questionid , c.categoryid
					FROM {$GLOBALS['tablePrefix']}questions_history qh, {$GLOBALS['tablePrefix']}catassoc_history c , {$GLOBALS['tablePrefix']}categoryassociations a 
					WHERE (qh.workflowstatus = '".WF_STATUS_AUTO_APPROVED."' OR qh.workflowstatus = '".WF_STATUS_APPROVED."')
					AND qh.questionid = c.questionid 
					AND c.questionid = a.questionid 
					AND c.categoryid = a.categoryid 
					AND qh.questionid IN ($historyQuestionIdsStr)
					$categoryRestrictSQL
					";
					$historyQuestionIdsQryRes = $GLOBALS['AKB_DB']->Query($historyQuestionIdsQry);
					$historyQuestion = array();
					
					if ($GLOBALS['AKB_DB']->CountResult($historyQuestionIdsQry) > 0) {
						while ($row = $GLOBALS['AKB_DB']->Fetch($historyQuestionIdsQryRes)) {
							$questionCat[$row['questionid']][] = $row['categoryid'];
						}
					}
				}
			}
			foreach ($questionCat as $k=>$v) {
				foreach ($v as $eachVal) {
					if (!isset($this->questionCountByCatId[$eachVal])) {
						$this->questionCountByCatId[$eachVal] = 0;
					}
					$this->questionCountByCatId[$eachVal]++;
				}
			}
		}

		/**
		* getCats
		* Returns an array of categories, each indented and prefixed depending
		* on it's position in the category structure. This function calls itself
		* recursively.
		*
		* @param string $stalk What to prefix a question with to signify it is
		* a descendant of its parent
		* @param int $parentid The category id to get descdendants of
		* @param string $prefix This string grows with whitespace depending on
		* the depth of the item in the tree
		*
		* @return array The formatted array of categories
		*/
		function getCats($stalk='`- ', $parentid=0, $prefix='') {
			static $c = null;
			
			$subs = array();
			$formatted = array();

			// If we don't have any data get it from the db
			$this->getCatsInfo();

			if (!isset($this->tree->nodesByPid[$parentid])) {
				return array();
			}

			include_once(dirname(__FILE__).'/class.categories.php');
			if (!$c) {
				$c = new AKB_CATEGORIES();
			}

			$cats_to_get = $this->tree->nodesByPid[$parentid];

			foreach ($cats_to_get as $k => $catid) {
				$cat = $this->catsById[$catid];


				if (!empty($prefix)) {
					$formatted[$cat['categoryid']] = $prefix.$stalk.$cat['name'];
				} else {
					$formatted[$cat['categoryid']] = $prefix.$cat['name'];
				}

				if ($c->CheckPass($catid)) {
					$subs = $this->getCats($stalk, $cat['categoryid'], $prefix.'&nbsp;&nbsp;&nbsp;&nbsp;');
					$formatted = $formatted + $subs;
				}
			}
			return $formatted;
		}

		/**
		* _GetSubCount
		* Returns the number of sub categories under a given categoryid
		*
		* @param int $catid The catid to get the number of subcats for
		*
		* @return int The number of sub categories of $catid
		*/
		function _GetSubCount($catid)
		{
			return $this->tree->GetNodeCount($catid);
		}

		/**
		* GetCatPathArray
		* Get the path to a category
		*
		* @param int $catid The id to get the path to
		*
		* @return arary An array of names to signify the trail to the category
		*/
		function GetCatPathArray($catid)
		{
			$catPath = array();

			$this->getCatsInfo();

			while ($catid > 0) {
				if (isset($this->catsById[$catid])) {
					$catPath[] = array($catid, $this->catsById[$catid]['name']);
					$catid = $this->catsById[$catid]['parentid'];
				} else {
					break;
				}
			}
			
			return array_reverse($catPath);
		}

		/**
		* GetCompleteCategoryPath
		* Get the complete path to the category as an html string with links
		*
		* @param int $categoryid The category at the end of the path
		*
		* @return string The html for the path
		*/
		function GetCompleteCategoryPath($categoryid)
		{
			$output = '';
			$catname = '';

			$catPath = $this->GetCatPathArray($categoryid);

			foreach ($catPath as $cat) {
				list($catid, $catname) = $cat;
				$output .= sprintf('%s/', $GLOBALS['AKB_CLASS_HELPER']->_MakeURLSafe($catname));
			}
						
			return $output;
		}

		/**
		* GetCategoryTrail
		* Get the trail for a category, can make the last item either text or
		* html
		*
		* @param int $categoryid The categoryid to end with
		* @param bool $all_links Make the last item a link or not
		*/
		function GetCategoryTrail($categoryid, $all_links=false)
		{
			$output = '';
			$catid = 0;
			$count = 0;

			$catPath = $this->GetCatPathArray($categoryid);

			if (!$catPath) {
				return false;
			}

			foreach ($catPath as $cat) {
				list($catid, $catname) = $cat;
				$GLOBALS['Link'] = GetUrl('category', $catid);
				$GLOBALS['Text'] = $catname;
				
				if ($all_links || ($count < sizeof($catPath)-1)) {
					$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('BreadcrumbLink');
				} else {
					$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('BreadcrumbText');
				}
				$count++;
			}

			return $output;
		}

		/**
		* GetNumQuestionsInCategory
		* Returns the number of questions in a category and can optionally
		* include the number of questions in subcategories in it's total
		*
		* @param int $categoryid The category id we are interested in
		* @param bool $includesubcats Include sub cats in our total ?
		*
		* @return int The number of questions total in $categoryid
		*/
		function GetNumQuestionsInCategory($categoryid, $includesubcats=true)
		{
			$numquestions = 0;
			$cats = array();
			$todo = array($categoryid);

			// Get our information if we dont already have it
			if (empty($this->questionCountByCatId)) {
				$this->getQuestCountInfo();
			}

			$this->getCatsInfo();
			
			// Work out what categories we need to get the count for
			// if we are getting the count including sub categories
			if ($includesubcats) {
				reset($todo);
				// We have to be careful with this loop since we are modifying
				// the variable we are looping over from inside the loop
				while (list($key, $catid) = each($todo)) {
					if (isset($this->tree->nodesByPid[$catid])) {
						foreach ($this->tree->nodesByPid[$catid] as $subcatid) {
							$subcat = $this->catsById[$subcatid];
							$todo[] = $subcat['categoryid'];
						}
					}
					if (isset($this->questionCountByCatId[$catid])) {
						$numquestions += $this->questionCountByCatId[$catid];
					}
				}
			} else {
				$numquestions = $this->questionCountByCatId[$categoryid];
			}

			return $numquestions;
		}

		/**
		* _MakeURLSafe
		* Make a string safe for being a url
		*
		* @param string $val The string to make safe
		*
		* @return string The safe string
		*/
		function _MakeURLSafe($val)
		{
			$val = str_replace('/', '{47}', $val);
			$val = str_replace('+', '{2B}', $val);
			$val = urlencode($val);
			return $val;
		}

		/**
		* _MakeURLNormal
		* Make a url which was made safe with _MakeURLSafe normal again
		*
		* @param string The sanitized string
		*
		* @return string The original string
		*/
		function _MakeURLNormal($val)
		{
			$val = urldecode($val);
			$val = str_replace('{2B}', '+', $val);
			$val = str_replace('{47}', '/', $val);
			return $val;
		}

		/**
		* GenerateToken
		* Generate a token to use when replacing glossary words
		*
		* @return string The token
		*/
		function GenerateToken()
		{
			$s = '';
			$l = 20;

			for (;strlen($s)<=$l;$s.=chr(rand($a=ord('A'),ord('Z'))+ rand()%2*(ord('a')-$a))) {
			}
			return '['.$s.']';
		}

		/**
		* GetGlossaryTerms
		* Get a list of glossary terms in a format which can be used for replacing
		* glossary words in a question's answer later on
		*
		* @return array The array of glossary terms
		*/
		function GetGlossaryTerms()
		{
			$arrWords = array();
			$query = sprintf('select * from %sglossary', $GLOBALS['tablePrefix']);
			$result = $GLOBALS['AKB_DB']->Query($query);

			while ($row = $GLOBALS['AKB_DB']->Fetch($result)) {
				$arrWords[] = array('word' => $row['word'],
					'desc' => $row['description'],
					'token' => $GLOBALS['AKB_CLASS_HELPER']->GenerateToken()
				);
			}

			return $arrWords;
		}

		/**
		* PrepareCommentAuthor
		* Create a string for the comment author depending on what we have for
		* $Name and $Email
		*
		* @param string $Name The name
		* @param string $email The email
		*
		* @return string The html for the persons name
		*/
		function PrepareCommentAuthor($Name, $Email)
		{
			$output = '';

			if (!empty($Name) && !empty($Email)) {
				$GLOBALS['Link'] = 'mailto:'.$Email;
				$GLOBALS['Text'] = htmlspecialchars($Name, ENT_QUOTES, $GLOBALS['charset']);
				$output = $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('Link');
			} else if (!empty($Email)) {
				$GLOBALS['Link'] = 'mailto:'.$Email;
				$GLOBALS['Text'] = htmlspecialchars($Email, ENT_QUOTES, $GLOBALS['charset']);
				$output = $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('Link');
			} else if (!empty($Name)) {
				$output = $Name;
			} else {
				$output = GetLang('Anonymous');
			}

			return $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders($output);
		}

		/**
		* getNumericCompareOptions
		* Get a string with html options for numeric comparisons
		*
		* @param string $selected Which operator is selected ?
		*
		* @return string The html string of options
		*/
		function getNumericCompareOptions($selected='>')
		{
			$fields = array (
				'<' => GetLang('lessThan'),
				'>' => GetLang('greaterThan'),
				'=' => GetLang('equalTo'),
				'<=' => GetLang('lessThan').' '.GetLang('or').' '.GetLang('equalTo'),
				'>=' => GetLang('greaterThan').' '.GetLang('or').' '.GetLang('equalTo'),
			);

			$options = '';
			foreach ($fields as $k => $v) {
				$GLOBALS['value'] = $k;
				$GLOBALS['text'] = $v;
				$GLOBALS['selected'] = ($k == $selected) ? ' selected="selected"' : '';
				$options .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('Option');
			}
			return $options;
		}

		/**
		* getNumericBracketOptions
		* Get a string with html options for numeric thresholds
		*
		* @param int $selected The threshold selected, if it isn't a threshold
		* that is reached then nothing is marked as selected
		* @param int $start The number to start counting
		* @param int $end The number to end counting
		* @param int $step The number to step by
		* @param string $pre Prefix the numbers with this string
		* @param string $post Suffix the numbers with this string
		*
		* @return string The html string of options
		*/
		function getNumericBracketOptions($selected=0, $start=0, $end=100, $step=25, $pre='', $post='%')
		{
			$options = '';
			foreach (range($start, $end) as $num) {
				if ($num % $step > 0) {
					continue;
				}
				$GLOBALS['value'] = $num;
				$GLOBALS['text'] = $pre.$num.$post;
				$GLOBALS['selected'] = ($num == $selected) ? ' selected="selected"' : '';
				$options .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('Option');
			}
			return $options;
		}

		/**
		* getRatedBracketOptions
		* Get a string with html options for levels of rating
		*
		* @param int $selected The threshold selected, if it isn't a threshold
		* that is reached then nothing is marked as selected
		*
		* @return string The html string of options
		*/
		function getRatedBracketOptions($selected='All')
		{
			$options = '';
			foreach (array('All', '0', '25', '50', '75') as $num) {
				$GLOBALS['value'] = $num;
				$GLOBALS['text'] = $GLOBALS['AKB_LANG']['Rated_'.$num];
				$GLOBALS['selected'] = ($num == $selected) ? ' selected="selected"' : '';
				$options .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('Option');
			}
			return $options;
		}

		/**
		* getAccessibleCats [DEPRECATED]
		* Get a list of all the categories the currently visiting user has
		* access to
		*
		* @param integer $parentid The id of the top most level to get info for
		*
		* @return array The array of categories or an empty array if they don't
		* have access to anything
		*/
		function getAccessibleCats($parentid=0)
		{
			// If we havn't loaded the category info yet, load it
			$this->getCatsInfo();

			// If there are no categories then return
			if (empty($this->tree->nodesByPid)) {
				return array();
			}

			$accessiblecats = array();
	
			if (isset($this->tree->nodesByPid[$parentid])) {
				foreach ($this->tree->nodesByPid[$parentid] as $catid) {
					$cat = $this->catsById[$catid];
					if (empty($cat['pass']) || trim($cat['pass']) == '') {
						$accessiblecats[] = $cat['categoryid'];
						$accessiblecats = array_merge($accessiblecats, $this->getAccessibleCats($cat['categoryid']));
						continue;
					}

					$cookie_name = 'akb_cat_pass_'.$cat['categoryid'];
					if (isset($_COOKIE[$cookie_name])
					&& $cat['pass'] == $_COOKIE[$cookie_name]) {
						$accessiblecats[] = $cat['categoryid'];
						$accessiblecats = array_merge($accessiblecats, $this->getAccessibleCats($cat['categoryid']));
						continue;
					}
				}
			}
			return $accessiblecats;
		}
		
		/**
		* deriveCategoriesByName
		* Takes a category name string and grabs the ID and all children ID.
		*
		* @param string $categoryName The name of the category to search on
		*
		* @return array The array of categories or an empty array if they don't
		* have access to anything
		*/		
		function deriveCategoriesByName($categoryName) {
			//Get the ID from the string
			$query = "
				SELECT categoryid
				FROM
					".$GLOBALS['tablePrefix']."categories
				WHERE
					name = '".$GLOBALS['AKB_DB']->Quote($categoryName)."'
			";
			$query .= $GLOBALS['AKB_DB']->AddLimit(0, 1);
			
			$categoryid = $GLOBALS['AKB_DB']->FetchOne($query);
			$this->getCatsInfo();
			
			$cat_array = array();
			if ($categoryid) {
				$cat_array = $this->tree->GetBranchFrom($categoryid,false);
				$cat_array[] = $categoryid;
			}
			
			return $cat_array;			
		}
		
		/**
		* GetApplies
		* Get a list of categories that the permissions of a group apply to
		*
		* @return array
		*/
		function GetApplies()
		{
			if (!isset($_SESSION['user'])) {
				return false;
			}
			
			$applies = array();
			if (is_array($_SESSION['user']->groups) && !empty($_SESSION['user']->groups)) {
				foreach ($_SESSION['user']->groups as $group) {
					if (isset($group->applies['category']) && is_array($group->applies['category'])) {
						$applies = array_merge($applies, $group->applies['category']);
					} else if (trim(strtolower($group->applies['category'])) == "all") {
						//Special case for when the "all" keyword is used. Need to get all of the categories
						//and return them. Then we can break out of the loop because this user obviously belongs to 
						//a group that has access to everything.
						$applies = $this->tree->GetBranchFrom(0, false);
						break;
					}
				}
			}
			return $applies;
		}

		/**
		* GetPermittedCats
		* Get an array of permitted category ids that the currently logged in
		* user is allowed to access taking into account where the category is
		* in the tree structure
		*
		* @return array
		*/
		function GetPermittedCats()
		{
			$applies = $this->GetApplies();
			$permitted = array();
			
			$this->getCatsInfo();
			
			if (!empty($applies)) {
				foreach ($applies as $catid) {
					$permitted[] = $catid;
					$permitted = array_merge($permitted,array_intersect($this->tree->GetBranchFrom($catid, false),$applies));
				}
			} else {
				$permitted = $this->tree->GetTreeDepthFirst();
			}
			
			return $permitted;
		}
		
		/**
		* valid_username
		*
		* @param integer $l the number
		*
		* @return bool
		*/
		function valid_username($n, $a=false)
		{
			return true;
		}
		
		/**
		* get1n
		*
		* @return e
		*/
		function get1n($i=3)
		{
			if (!isset($GLOBALS["licenseKey"])) {
				return '';
			}
			$l = $GLOBALS["licenseKey"];
			$l = str_replace('-', '', $l);
			$l = preg_replace('/^'.PRODUCT_ID.'/', '', $l);
			$l = urldecode($l);
			$l = base64_decode($l);
			$arrData = explode("|", $l);

			if ($i == 3) {
				$t=($arrData[$i]=='')?'Professional':$arrData[$i];
				return ($i==3 && $arrData[2]!='') ? "$t - Trial":$t;
			}
			return $arrData[$i];
		}
		
		/**
		*validUrl
		*
		*/
		function validUrl( $url )
		{
			return (preg_match('/^en{1}/', strtolower($url)) || preg_match('/^or{1}/', strtolower($url)));
		}
		
	}

?>
